package pl.multimedialne.carculator.sensors;

import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

public class GPS {
	static private GPS instance = null;

	static public GPS getInstance() {
		if (instance == null) {
			instance = new GPS();
		}
		return instance;
	}

	private boolean enabled = true;
	private Float speed = 0.0f;

	private long lastTimestamp = -1;
	private Location lastLocation = null;

	private GPS() {
	}

	private double distance(Location one, Location two) {
		int R = 6371000;
		double dLat = toRad(two.getLatitude() - one.getLatitude());
		double dLon = toRad(two.getLongitude() - one.getLongitude());
		double lat1 = toRad(one.getLatitude());
		double lat2 = toRad(two.getLatitude());
		double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2)
				* Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
		double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
		double d = R * c;
		return d;
	}

	private static double toRad(double d) {
		return d * Math.PI / 180;
	}

	public void initialize(Activity activity) {
		LocationManager locationManager = (LocationManager) activity
				.getSystemService(Context.LOCATION_SERVICE);
		enabled = locationManager
				.isProviderEnabled(LocationManager.GPS_PROVIDER);
		if (!enabled)
			return;

		final GPS that = this;
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
				0, new LocationListener() {
					@Override
					public void onStatusChanged(String provider, int status,
							Bundle extras) {
					}

					@Override
					public void onProviderEnabled(String provider) {
					}

					@Override
					public void onProviderDisabled(String provider) {
					}

					@Override
					public void onLocationChanged(Location location) {
						if (that.lastTimestamp == -1) {
							that.lastTimestamp = location.getTime();
							that.lastLocation = location;
							return;
						}

						float timeDelta = (location.getTime() - that.lastTimestamp) / 1000.0f / 1000.0f / 1000.0f;

						setSpeed((float) (distance(location, lastLocation)
								/ timeDelta * 60 * 60 / 1000));
						lastLocation = location;
					}
				});
	}

	private void setSpeed(float speed) {
		synchronized (this.speed) {
			this.speed = speed;
		}
	}

	public float getSpeed() {
		synchronized (this.speed) {
			return speed;
		}
	}

	public boolean isEnabled() {
		return enabled;
	}

	public Float getAcceleration() {
		return 0.0f;
	}

}
